package com.chang.ware.listener;

import com.chang.common.to.mq.StockLockedTo;
import com.chang.ware.service.WareSkuService;
import com.rabbitmq.client.Channel;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

/**
 * @author: changzhenxi
 * @date: 2025年03月17日 11:08
 * @Version: 1.0
 * @description:
 */
@Slf4j
@Service
@RabbitListener(queues = "stock.release.queue")
public class StockReleaseListener {

    @Resource
    WareSkuService wareSkuService;

    /**
     * 下单成功，库存锁定成功，业务调用失败，导致订单回滚  之前的订单就要自动回滚
     * <p>
     * 这里还有另外的情况就是部分商品锁定失败引起的回滚会导致库存工作单连带一起回滚
     * <p>
     * 注意这里有个很重要的点 死信队列中的消息在这里被监听消费之后不管是否解锁成功，消息都会被删除
     * 如果解锁失败，已经需要告诉服务，重试解锁
     * 所以需要使用手动ack机制
     *
     * @param stockLockedTo
     * @param message
     */
    @RabbitHandler
    public void handleStockLockedRelease(StockLockedTo stockLockedTo, Message message, Channel channel) throws Exception {
        try {
            // 判断消息是否为二次派发
            // Boolean redelivered = message.getMessageProperties().getRedelivered();
            wareSkuService.unlockStock(stockLockedTo, message, channel);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            // 如果出现异常,则拒绝消息重新归队
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
        }
    }

    // 主动事务补偿
    @RabbitHandler
    public void handleOrderCloseRelease(String orderSn, Message message, Channel channel) throws Exception {
        log.info("接收到订单:{}关闭消息,准备解锁库存", orderSn);
        try {
            wareSkuService.unlockStock(orderSn, message, channel);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            // 如果出现异常,则拒绝消息重新归队
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
        }
    }


}
